<template>
  <div class="app-container">
    <div class="form-left left">
      <el-form ref="form" v-loading="initLoading" :model="form" :rules="rules" label-width="80px" :validate-on-rule-change="false">
        <el-form-item label="任务名称" prop="title"><el-input v-model="form.title" /></el-form-item>
        <el-form-item label="模板名称" class="tpl_name">
          <el-select v-if="formData.length > 0" v-model="form.tpl_id" class="tpl_select" placeholder="请选择模板" @change="tplChange">
            <el-option v-for="(item, index) in formData" :key="item.id" :label="item.title" :value="item.id" />
          </el-select>
          <el-select v-else v-model="form.tpl_id" class="tpl_select" placeholder="暂无可用模板，请先在模板配置模板" disabled>
            <el-option v-for="(item, index) in formData" :key="item.id" :label="item.title" :value="item.id" />
          </el-select>
        </el-form-item>
        <div v-if="tpl_total_data.length > 0">
          <el-form-item v-for="(item, index) in tpl_total_data" :label="item.label" :prop="item.value">
            <div v-if="!item.isTime" class="form-msg">
              <el-input v-model="form[item.value]" @input="inputChange(item)" />
              <!-- <span class="lineW"></span>
              <el-color-picker v-model="item.color" size="small" @change="colorChange(item)"></el-color-picker>
              <span class="color-txt"></span> -->
            </div>
            <div v-else class="form-msg">
              <el-date-picker
                v-model="form[item.value]"
                class="datePickerBox"
                format="yyyy-MM-dd HH:mm:ss"
                value-format="yyyy-MM-dd HH:mm:ss"
                type="datetime"
                placeholder="选择日期时间"
                @change="timeChange(item)"
              />
              <!-- <span class="lineW"></span>
              <el-color-picker v-model="item.color" size="small"></el-color-picker>
              <span class="color-txt"></span> -->
            </div>
          </el-form-item>
        </div>
        <el-form-item label="跳转方式" prop="jump_type">
          <el-radio-group v-model="form.jump_type" @change="jumptypeChange">
            <el-radio :label="1">跳转网页</el-radio>
            <el-radio :label="2">跳转小程序</el-radio>
            <el-radio :label="0">不跳转</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item v-if="form.jump_type != 0" label="页面地址" prop="jump_url"><el-input v-model="form.jump_url" /></el-form-item>
        <el-form-item label="关注时间" prop="date_range" class="date-picker-box">
          <el-date-picker
            v-model="form.date_range"
            class="tpl_picker_time"
            format="yyyy-MM-dd"
            value-format="yyyy-MM-dd"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            @change="dateChange"
          />
          <span class="dateRangeIconWarn">公众号粉丝关注时间筛选</span>
        </el-form-item>
        <el-form-item label="预计发送">
          <div class="due_num_box">
            <span class="due_num">{{ due_num }}</span>
            <span v-if="exceed == 1" class="warnTxt1">为保证发送效果，单次发送量不得大于500条</span>
          </div>
          <div class="warnTxt2">
            今天还可发送
            <span class="txt">{{ remain }}</span>
            条模板消息，若全部消耗将影响网站日常通知
          </div>
        </el-form-item>
        <el-form-item>
          <div class="btn-box"><el-button type="primary" :loading="loading" @click="onSubmit('form')">立即群发</el-button></div>
        </el-form-item>
      </el-form>
    </div>
    <div class="res-right right">
      <div class="res-title">效果预览</div>
      <div ref="refBox" :class="fixedToTop ? 'res-view toTop' : 'res-view'">
        <div v-if="tpl_total_data.length > 0" class="res-view-content">
          <div class="res-title">
            <span>{{ previewContent.tpl_name }}</span>
            <span class="circle-icon">···</span>
          </div>
          <div v-for="(item, index) in tpl_total_data" :key="index" class="res-desc">
            <div class="res-label">{{ item.label }}:</div>
            <div v-if="item.value == 'first' && item.keyword == ''" class="res-content" :style="{ color: item.color }" />
            <div v-else class="res-content" :style="{ color: item.color }">{{ item.keyword }}</div>
          </div>
          <div v-if="form.jump_type == 1" class="res-link">
            <span>查看详情</span>
            <span class="rt_icon">></span>
          </div>
          <div v-if="form.jump_type == 2" class="res-link">
            <span>查看详情</span>
            <span class="rt_icon">
              <span class="rt_txt">小程序</span>
              >
            </span>
          </div>
        </div>
        <div v-else class="res-view-content">
          <div class="noDataWarn1">请先选择模板</div>
          <div class="noDataWarn2">等待填写模板的内容</div>
        </div>
        <!-- <div class="res-view-warn">部分模板的【消息描述】由于微信限制，文字颜色固定为灰色，请以在手机端预览的效果为准。</div> -->
      </div>
    </div>
    <el-dialog title="" :visible.sync="pressLoading" width="400px" center :close-on-click-modal="false" :show-close="false">
      <el-progress type="line" :percentage="progressVal" />
      <div class="pro-txt">正在发送，请耐心等待</div>
    </el-dialog>
  </div>
</template>
<script>
import { getDueCountByTimes, wechatMassTplList, sendJob, wechatMassTplSendQuota, queueTask, getQueueSurvey } from '@/api/massSMS'
export default {
  props: ['massCopyData'],
  data() {
    return {
      loading: false,
      initLoading: false,
      previewContent: {},
      form: {
        tpl_id: '',
        title: '', // 任务名称
        jump_type: 1, // 跳转方式
        jump_url: '', // 跳转页面地址
        date_range: '',
        first: ''
      },
      rules: {
        title: [{ required: true, message: '请输入任务名称', trigger: 'blur' }],
        jump_url: [{ required: true, message: '请输入页面地址', trigger: 'blur' }],
        jump_type: [{ required: true, message: '请选择跳转方式', trigger: 'change' }],
        date_range: [
          {
            type: 'array',
            required: true,
            message: '请选择日期区间',
            fields: {
              0: {
                // type: 'string', //tpye类型试情况而定,所以如果返回的是date就改成date
                required: true,
                trigger: 'change',
                message: '请选择开始日期'
              },
              1: {
                required: true,
                trigger: 'change',
                message: '请选择结束日期'
              }
            }
          }
        ]
      },
      no_time_total: 0,
      sync_num: 0,
      due_num: 0, // 预计发送多少条
      exceed: 0, // 提示发送量超出
      tpl_total_data: [],
      formData: [],
      remain: 0, // 当天剩余调用次数
      pressLoading: false,
      progressVal: 0,
      queue_sync_num: 0, // 发送执行次数
      offsetTop: 0,
      offsetHeight: 0,
      fixedToTop: false
    }
  },
  watch: {
    massCopyData(newValue, oldValue) {
      if (newValue) {
        if (this.tpl_total_data.length > 0) {
          this.form.title = newValue.title
          this.form.tpl_id = newValue.tpl_id
          this.initTplData()
          this.form.jump_type = newValue.jump_type
          this.form.jump_url = newValue.jump_url
          this.tpl_total_data.forEach(item => {
            item.keyword = newValue.tpl_data[item.value].value
            item.color = newValue.tpl_data[item.value].color
            this.form[item.value] = newValue.tpl_data[item.value].value
          })
        }
      }
    }
  },
  created() {},
  mounted() {
    this.initData()
    this.getWechatMassTplSendQuota()
    this.$nextTick(() => {
      this.$refs.form.clearValidate()
      // 获取吸顶元素的dom
      const refBox = this.$refs.refBox
      // 吸顶元素到top的距离
      this.offsetTop = refBox.offsetTop
      // 元素自身的高度
      this.offsetHeight = refBox.offsetHeight
      // 监听滚动条
      window.addEventListener('scroll', this.handleScroll)
    })
  },
  destroyed() {
    window.removeEventListener('scroll', this.handleScroll)
  },
  methods: {
    handleScroll() {
      // 得到页面滚动的距离，兼容写法
      const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
      // 判断页面滚动的距离是否大于吸顶元素的位置
      // this.fixedToTop = scrollTop > this.offsetTop - this.offsetHeight;
      this.fixedToTop = scrollTop > 270
      // console.log(scrollTop,this.offsetTop,this.offsetHeight,this.fixedToTop)
    },
    inputChange(item) {
      this.tpl_total_data.forEach((items, index) => {
        if (item.value == items.value) {
          this.tpl_total_data[index].keyword = this.form[item.value]
        }
      })
    },
    timeChange(item) {
      this.tpl_total_data.forEach((items, index) => {
        if (item.value == items.value) {
          this.tpl_total_data[index].keyword = this.form[item.value]
        }
      })
    },
    colorChange(item) {},
    jumptypeChange() {
      if (this.form.jump_type == 0) {
        this.rules.jump_url = []
      } else {
        this.rules.jump_url = [{ required: true, message: '请输入页面地址', trigger: 'blur' }]
      }
    },
    getWechatMassTplSendQuota() {
      wechatMassTplSendQuota().then(res => {
        if (res.code == 200) {
          this.remain = res.data.remain
        }
      })
        .catch(() => {})
    },
    tplChange() {
      this.$nextTick(() => {
        this.$refs.form.clearValidate()
        this.formData.forEach((item, index) => {
          if (item.id == this.form.tpl_id) {
            this.previewContent.tpl_name = item.tpl_name
            this.tpl_total_data = []
            for (let i = 0; i < this.formData[index].tpl_param.length; i++) {
              const obj = {}
              obj.isTime = this.formData[index].tpl_param[i].indexOf('时间') != -1
              obj.label = this.formData[index].tpl_param[i]
              obj.value = this.formData[index].tpl_data[i]
              obj.color = obj.value == 'first' ? '#999999' : '#333333'
              obj.keyword = ''
              this.tpl_total_data.push(obj)
              const messageError = '请输入' + obj.label
              this.$set(this.form, obj.value, '')
              if (this.formData[index].tpl_param[i].indexOf('时间') == -1) {
                // 不包含时间 == -1
                this.$set(this.rules, obj.value, [{ required: true, message: messageError, trigger: 'blur' }])
              } else {
                this.$set(this.rules, obj.value, [{ required: true, message: messageError, trigger: 'change' }])
              }
            }
          }
        })
      })
    },
    initData() {
      wechatMassTplList({ menu: 1 }).then(response => {
        if (response.code == 200) {
          const data = [...response.data]
          if (data.length > 0) {
            this.formData = data
            this.form.tpl_id = data[0].id
            this.initLoading = false
            this.previewContent.tpl_name = this.formData[0].title
            this.initTplData()
          } else {
            this.tpl_total_data = []
            this.formData = []
            this.form.tpl_id = ''
          }
        }
      })
        .catch(() => {})
    },
    // 初始化默认模板
    initTplData() {
      this.tpl_total_data = []
      let initTplData = {} // 默认模板
      this.formData.forEach(item => {
        if (item.id == this.form.tpl_id) {
          initTplData = item
        }
      })
      for (let i = 0; i < initTplData.tpl_param.length; i++) {
        const obj = {}
        obj.isTime = initTplData.tpl_param[i].indexOf('时间') != -1
        obj.label = initTplData.tpl_param[i]
        obj.value = initTplData.tpl_data[i]
        obj.color = obj.value == 'first' ? '#999999' : '#333333'
        obj.keyword = ''
        this.tpl_total_data.push(obj)
        const messageError = '请输入' + obj.label
        this.$set(this.form, obj.value, null)
        if (initTplData.tpl_param[i].indexOf('时间') == -1) {
          // 不包含时间 == -1
          this.$set(this.rules, obj.value, [{ required: true, message: messageError, trigger: 'blur' }])
        } else {
          this.$set(this.rules, obj.value, [{ required: true, message: messageError, trigger: 'change' }])
        }
        this.$refs.form.clearValidate(['jump_url'])
        this.$refs.form.clearValidate(['date_range'])
      }
    },
    dateChange() {
      const params = {
        date_range: this.form.date_range
      }
      getDueCountByTimes(params).then(res => {
        if (res.code == 200) {
          this.due_num = res.data.due_num
          this.exceed = res.data.exceed
        }
      })
      this.$forceUpdate()
    },
    colorDescChange() {},
    onSubmit(formName) {
      if (this.due_num > 500) {
        this.$message.error('单次任务最多可发送500条，请重新选择关注公众号时间范围！')
        return
      }
      if (this.due_num > 0 && this.due_num <= this.remain) {
        let keyword = ''
        const params = { ...this.form }
        this.tpl_total_data.forEach(item => {
          const arr = []
          const obj = {}
          obj.value = item.keyword
          obj.color = item.color
          arr.push(obj)
          keyword = item.value
          params[keyword] = obj
        })
        this.loading = true
        this.$refs[formName].validate(valid => {
          if (valid) {
            sendJob(params)
              .then(res => {
                if (res.code == 200) {
                  this.$message.success(res.message)
                  this.mass_id = res.data.mass_id
                  this.getQueueSurveyData(this.mass_id)
                } else {
                  this.loading = false
                }
              })
              .catch(() => {
                this.loading = false
              })
          } else {
            this.moveToErr()
            this.loading = false
            return false
          }
        })
      } else if (this.due_num == 0) {
        this.$message.error('预计发送数为0，请重新选择关注时间')
      } else if (this.due_num > this.remain) {
        this.$message.error('预计发送数超过今日可发送模板消息条数')
      }
    },
    doQueueTask() {
      this.pressLoading = true
      const requestList = []
      const progressValPre = 100 / this.queue_sync_num
      this.progressVal = progressValPre
      for (let i = 0; i < this.queue_sync_num; i++) {
        requestList.push(queueTask)
      }
      let j = 0 // 记录发送的请求个数
      const send = async () => {
        if (j >= requestList.length) {
          this.getQueueSurveyData(this.mass_id)
          this.loading = false
          this.pressLoading = false
          // 发送完毕
          return
        }
        await requestList[j]({ mass_id: this.mass_id })
        if (this.progressVal <= 100 - progressValPre) {
          this.progressVal += progressValPre
        }
        j++
        send()
      }
      send() // 发送请求
    },
    getQueueSurveyData(mass_id) {
      getQueueSurvey({ mass_id: mass_id }).then(res => {
        if (res.code == 200) {
          if (res.data.sync_num != 0) {
            this.queue_sync_num = res.data.sync_num
            this.doQueueTask()
          } else {
            this.loading = false
            this.getWechatMassTplSendQuota()
            const due_num = res.data.due_num // 总数
            const success_num = res.data.success_num // 成功
            const failed_num = res.data.failed_num // 失败
            const error_num = res.data.error_num // 错误
            this.$message.success('发送总数：' + due_num + '，成功：' + success_num + '，失败：' + failed_num + '，错误：' + error_num)
          }
        }
      })
        .catch(() => {})
    },
    // 自动定位到表单报错项
    moveToErr() {
      this.$nextTick(() => {
        const isError = document.getElementsByClassName('is-error')
        // console.log(isError);
        if (isError.length) {
          isError[0].scrollIntoView({
            block: 'center',
            behavior: 'smooth'
          })
          // 这个当滑动到报错项之后自动获取输入框的焦点，方便用户直接进行输入，延迟 800ms 是因为需要都能到定位成功后在进行获取焦点体验更好一些
          setTimeout(() => {
            if (isError[1].previousElementSibling.querySelector('input')) {
              isError[1].previousElementSibling.querySelector('input').focus()
            }
          }, 800)
        }
      })
    }
  }
}
</script>

<style lang="scss" scope>
.app-container {
  overflow: hidden;

  .form-left {
    width: 530px;
    float: left;
    .radio-item {
      &:first-child {
        margin-bottom: 15px;
      }
    }
    .form-msg {
      display: flex;
      align-items: center;
      .lineW {
        margin-left: 15px;
      }
      .color-txt {
        display: block;
        width: 100px;
        margin-left: 15px;
      }
      .datePickerBox {
        width: 100%;
      }
    }
    .line {
      text-align: center;
    }
    .due_num_box {
      display: flex;
      align-items: center;
      .warnTxt1 {
        margin-left: 15px;
        font-size: 12px;
        color: #a4a4a4;
        background: url('../../../../assets/images/warnIcon.png') 5px center no-repeat;
        background-size: 14px 14px;
        box-sizing: border-box;
        padding-left: 22px;
        line-height: 15px;
        padding-top: 1px;
      }
      .due_num {
        color: #ff6600;
        font-size: 20px;
        font-weight: bold;
      }
    }
    .warnTxt2 {
      box-sizing: border-box;
      font-size: 12px;
      margin-bottom: 35px;
      line-height: 15px;
      color: #a4a4a4;
      .txt {
        color: #ff6600;
        font-weight: bold;
        padding: 0 3px;
      }
    }
  }
  .res-right {
    width: 470px;
    float: left;
    display: flex;
    justify-content: center;
    margin-left: 60px;
    .res-view {
      width: 360px;
      height: 610px;
      background: url('../../../../assets/images/mobileModule.png') left center no-repeat;
      background-size: 100% 100%;
      margin: 5px 0;
      padding-top: 116px;
      &.toTop {
        position: fixed;
        top: 80px;
        left: 942px;
      }
      .res-view-warn {
        width: 230px;
        height: auto;
        margin: 0 auto;
        padding: 15px 0;
        font-size: 12px;
        color: #888785;
        text-align: justify;
        line-height: 18px;
      }
      .res-view-content {
        width: 230px;
        height: auto;
        margin: 0 auto;
        background: #fff;
        padding: 0 14px;
        border-radius: 10px;
        .res-time {
          height: 50px;
          line-height: 50px;
          font-size: 14px;
          border-bottom: 1px solid #ececec;
          color: #9d9f9d;
        }
        .res-title {
          color: #333;
          font-size: 14px;
          padding: 20px 0 25px;
          display: flex;
          align-items: center;
          justify-content: space-between;
          .circle-icon {
            font-size: 14px;
            color: #999;
            font-weight: bold;
          }
        }
        .res-desc {
          color: #666;
          font-size: 12px;
          padding-bottom: 15px;
          display: flex;
          align-items: baseline;
          justify-content: flex-start;
          width: 100%;
          .res-label {
            color: #999;
            display: block;
            width: 60px;
          }
          .res-content {
            display: block;
            width: calc(100% - 60px);
            word-wrap: break-word;
            white-space: pre-wrap;
            word-break: break-all;
            &.res-content-all {
              width: 100%;
            }
          }
        }
        .res-link {
          border-top: 1px solid #e8e8e8;
          padding: 12px 0;
          font-size: 14px;
          display: flex;
          justify-content: space-between;
          .rt_icon {
            color: #b8b8b8;
            .rt_txt {
              color: #333;
              padding-right: 6px;
              background: url('../../../../assets/images/miniprogram.png') left center no-repeat;
              background-size: 11px 11px;
              box-sizing: border-box;
              padding-left: 16px;
            }
          }
        }
      }
      .noDataWarn1 {
        font-size: 14px;
        padding: 25px 0 15px;
        color: #999;
      }
      .noDataWarn2 {
        font-size: 12px;
        padding-bottom: 25px;
        color: #999;
      }
    }
  }
}

.tpl_name {
  ::v-deep .el-form-item__label {
    line-height: 13px;
    background: red;
  }
  .tpl_select {
    width: 100%;
  }
}
.date-picker-box {
  .tpl_picker_time {
    width: 260px !important;
  }
  .dateRangeIconWarn {
    font-size: 12px;
    color: #a4a4a4;
    background: url('../../../../assets/images/warnIcon.png') 5px center no-repeat;
    background-size: 14px 14px;
    box-sizing: border-box;
    padding-left: 23px;
  }
}
.btn-box {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  .num-progress {
    margin-left: 30px;
    display: flex;
    align-items: center;
  }
}
.num-progress {
  display: flex;
  justify-content: center;
  margin-bottom: 20px;
}
.pro-txt {
  text-align: center;
  font-size: 14px;
  color: #333;
  margin-bottom: 20px;
  margin-top: 20px;
}
</style>
